package kr.ac.ssu.ailab.Model.Data;

import java.awt.Point;

import kr.ac.ssu.ailab.Control.CellControl;
import kr.ac.ssu.ailab.View.SeqTest;

/**
 * 맵을 구성하는 기초단위인 Cell 클래스
 * 
 * @author Neil
 * 
 */
public class Cell
{
	/* Constant Values */
	public static final double DEF_WEIGHT = 1.00;
	private int type;
	private int threatenLevel;
	private double distFromStart;
	private double distFromFinish;
	private double weight;
	private double totalLv1GraphWeight;
	private double fromStartNodeGraphWeightLv1;
	private double graphWeight_Upgrade;
	private Point position;
	private Point parent;
	private Point graphParent;
	private int isIncludedIn;
	private boolean isObstacle;
	private boolean isStand;

	/**
	 * 생성자
	 * 
	 * @param position
	 */
	public Cell(Point position)
	{
		this.type = CellControl.NORMAL;
		this.threatenLevel = 100;

		this.distFromStart = 0;
		this.distFromFinish = 0;
		this.weight = DEF_WEIGHT;
		this.totalLv1GraphWeight = -1;
		this.fromStartNodeGraphWeightLv1 = -1;
		this.graphWeight_Upgrade = 0;

		this.position = position;
		this.parent = null;
		this.graphParent = null;

		this.isIncludedIn = Integer.MAX_VALUE;

		this.isObstacle = false;
		this.isStand = false;

	}

	/**
	 * Lv1 Graph 의 TotalWeight를 get 하는 메소드
	 * 
	 * @return Lv1 Graph �� TotalCost �� ��ȯ�Ѵ�
	 */
	public double getGraphTotalWeightLv1()
	{
		if (this == SeqTest.mapControl.getStartCell())
		{
			return 0;
		}
		return totalLv1GraphWeight;
	}

	/**
	 * Lv1 Graph 의 시작노드로 부터 현재까지의 그래프 코스트를 get 하는 메소드
	 * 
	 * @return
	 */
	public double getFromStartNodeGraphLv1Weight()
	{

		if (this == SeqTest.mapControl.getStartCell())
		{
			return 0;
		}
		return fromStartNodeGraphWeightLv1;
	}

	/**
	 * Lv1 Graph 의 TotalWeight를 set 하는 메소드
	 * 
	 * @param hueristic
	 */
	public void setGraphTotalWeightLv1(double hueristic)
	{
		totalLv1GraphWeight = fromStartNodeGraphWeightLv1 + hueristic;

	}

	/**
	 * Lv1 Graph 의 시작노드로 부터 현재까지의 그래프 코스트를 set 하는 메소드
	 * 
	 * @param fromStartNodeGraphWeight
	 */
	public void setFromStartNodeGraphLv1Weight(double fromStartNodeGraphWeight)
	{
		this.fromStartNodeGraphWeightLv1 = fromStartNodeGraphWeight;
	}

	/**
	 * Cell 의 Type 을 get 하는 메소드
	 * 
	 * @return
	 */
	public int getType()
	{
		return type;
	}

	/**
	 * Cell Type 을 set 하는 메소드
	 * 
	 * @param type
	 */
	public void setType(int type)
	{
		this.type = type;
	}

	/**
	 * Cell 이 Start 지점으로부터 얼마나 떨어졌는지 get 하는 method
	 * 
	 * @return
	 */
	public double getDistFromStart()
	{
		if (this == SeqTest.mapControl.getStartCell())
			return 0;
		return distFromStart;
	}

	/**
	 * Cell 이 Start 지점으로부터 얼마나 떨어졌는지 set 하는 method
	 * 
	 * @param distFromStart
	 */
	public void setDistFromStart(double distFromStart)
	{
		this.distFromStart = distFromStart;
	}

	/**
	 * Cell 이 Finish 지점으로부터 얼마나 떨어졌는지 get 하는 method
	 * 
	 * @return
	 */
	public double getDistFromFinish()
	{
		return distFromFinish;
	}

	/**
	 *Cell 이 Finish 지점으로부터 얼마나 떨어졌는지 set 하는 method
	 * 
	 * @param distFromFinish
	 */
	public void setDistFromFinish(double distFromFinish)
	{
		this.distFromFinish = distFromFinish;
	}

	/**
	 * Cell 의 weight 를 get 하는 method
	 * 
	 * @return
	 */
	public double getWeight()
	{
		return weight;
	}

	/**
	 * Cell 의 weight 를 set 하는 method
	 * 
	 * @param weight
	 */
	public void setWeight(double weight)
	{
		this.weight = weight;
	}

	/**
	 * Cell 의 Position 를 get 하는 method
	 * 
	 * @return
	 */
	public Point getPosition()
	{
		return position;
	}

	/**
	 * Cell 의 Position 를 set 하는 method
	 * 
	 * @param x
	 * @param y
	 */
	public void setPosition(int x, int y)
	{
		position = new Point(x, y);
	}

	/**
	 * 셀이 어느 클러스터에 속했는지 알수 있게 클러스터의 일련번호를 set 하는 메소드
	 * 
	 * @param isIncludedIn
	 */
	public void setIsIncludedIn(int isIncludedIn)
	{
		this.isIncludedIn = isIncludedIn;
	}

	/**
	 * 셀이 어느 클러스터에 속했는지 알수 있게 클러스터의 일련번호를 get 하는 메소드
	 * 
	 * @return
	 */
	public int getIsIncludedIn()
	{
		return isIncludedIn;
	}

	/**
	 * 적의 사정거리와 연관이 있는 set 하는 메소드
	 * 
	 * @param alpha
	 */
	public void setThreatenLevel(int alpha)
	{
		this.threatenLevel = alpha;
	}

	public int getThreatenLevel()
	{
		return this.threatenLevel;
	}

	/**
	 * Cell 의 Parent Point 를 set 하는 메소드
	 * 
	 * @param position
	 */
	public void setParentPoint(Point position)
	{
		if (this.parent == null)
			this.parent = position;
		if (position == null)
		{
			this.parent = null;
		}
	}

	/**
	 * Cell 의 Parent Point 를 get 하는 메소드
	 * 
	 * @return
	 */
	public Point getParentPoint()
	{
		return parent;
	}

	/**
	 * 
	 * Cell 의 Graph Parent Point 를 get 하는 메소드
	 * 
	 * @return
	 */
	public Point getGraphParent()
	{
		return graphParent;
	}

	/**
	 * Cell 의 Graph Parent Point 를 set 하는 메소드
	 * 
	 * @param position
	 */
	public void setGraphParent(Point position)
	{
		if (this.graphParent == null)
			this.graphParent = position;
		if (position == null)
			this.graphParent = null;
	}

	/**
	 * Cell 의 obstacle 유무를 set 하는 메소드
	 * 
	 * @param isObstacle
	 */
	public void setObstacle(boolean isObstacle)
	{
		this.isObstacle = isObstacle;
	}

	/**
	 * Cell 의 obstacle 유무를 get 하는 메소드
	 * 
	 * @return
	 */
	public boolean isObstacle()
	{
		return isObstacle;
	}

	/**
	 * Cell 의 StandCell 유무를 get 하는 메소드
	 * 
	 * @return
	 */
	public boolean getStandCell()
	{
		return isStand;
	}

	/**
	 * Graph Weight set 하는 메소드
	 * 
	 * @param weight
	 */
	public void setFromNowGraphWeight(double weight)
	{
		this.graphWeight_Upgrade = weight;

	}

	/**
	 * Graph Weight 를 get 하는 메소드
	 * 
	 * @return
	 */
	public double getFromGraphWeight()
	{

		return this.graphWeight_Upgrade;
	}

	public boolean equals(Object object)
	{
		if (object instanceof Cell)
		{
			Cell test = (Cell) object;
			if ((this.getPosition().x == test.getPosition().x)
					&& this.getPosition().y == test.getPosition().y)
				return true;
		}
		return false;
	}

	public int hashCode()
	{
		String code = "" + position.x + position.y;
		return code.hashCode();
	}

}
